package io.jee.medusa.orm;

import java.util.List;
import java.util.Properties;

import javax.annotation.Resource;
import javax.sql.DataSource;

import org.springframework.beans.BeansException;
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import io.jee.medusa.ORMProperties;

@Configuration
@EnableTransactionManagement
@EnableConfigurationProperties({ORMProperties.class, JpaProperties.class})
public class HibernateConfig implements ApplicationContextAware {
	
	@Resource
	private DataSource dataSource;
	@Resource
	private ORMProperties ormProperties;
	@Resource
	private JpaProperties jpaProperties;
	
	private List<String> basePackages;
	
	@Bean
	public LocalSessionFactoryBean sessionFactory() {
		LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
		sessionFactory.setDataSource(dataSource);
		sessionFactory.setPackagesToScan(basePackages.toArray(new String[basePackages.size()]));
		sessionFactory.setPhysicalNamingStrategy(new PrefixPhysicalNamingStrategy(ormProperties.getPrefix()));
		Properties hibernateProperties = new Properties();
		hibernateProperties.put("hibernate.dialect", "org.hibernate.dialect.MySQL57InnoDBDialect");
		hibernateProperties.put("hibernate.format_sql", "true");
		hibernateProperties.put("hibernate.hbm2ddl.auto", "update");
		hibernateProperties.put("hibernate.default_batch_fetch_size", "16");
		hibernateProperties.put("hibernate.current_session_context_class", "org.springframework.orm.hibernate5.SpringSessionContext");
		hibernateProperties.putAll(jpaProperties.getProperties());
		sessionFactory.setHibernateProperties(hibernateProperties);
		return sessionFactory;
	}
	
	@Bean
    public PlatformTransactionManager transactionManager() {
        return new HibernateTransactionManager(sessionFactory().getObject());
    }
	
	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		basePackages = AutoConfigurationPackages.get(applicationContext);
	}
	
}
